﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Com.CloudTalk.Data;

namespace Com.CloudTalk.Controller
{
    public class CTChatRoom
    {
        public int ID { get; private set; }
        public string Name { get; set; }
        public List<CTClient> ClientList { get; set; }

        public CTChatRoom(string _sName, int _nID)
        {
            this.ID = _nID;
            this.Name = _sName;
            this.ClientList = new List<CTClient>();

            using (CloudTalkEntities db = new CloudTalkEntities())
            {
                ChatRoom thisRoom = db.ChatRoom
                    .Include(r => r.Clients)
                    .FirstOrDefault(cr => cr.ID == this.ID);

                thisRoom.Clients.ToList().ForEach(cl =>
                {
                    this.ClientList.Add(new CTClient(cl.Name, cl.Email));
                });
            }
        }

        public CTChatRoom(int _nID) : this(null, _nID)
        {
            
        }

        internal CTClient AddClient(
            string _sName,
            string _sEmail,
            RoleTypes _eRole)
        {
            using (CloudTalkEntities db = new CloudTalkEntities())
            {
                ChatRoom thisRoom = db.ChatRoom
                    .Include(r => r.Clients)
                    .FirstOrDefault(cr => cr.ID == this.ID);

                Client newClient = db.Client.FirstOrDefault(cl => cl.Email == _sEmail);

                if (newClient == null)
                {
                    // new client, add it to the database
                    Role clientRole = Role.GetRoleByName(Enum.GetName(typeof(RoleTypes), _eRole));
                    newClient = Client.CreateClient(_sEmail, _sName);
                    newClient.RoleReference.EntityKey = clientRole.EntityKey;
                    db.AddToClient(newClient);
                    db.SaveChanges();
                }
                else
                {
                    if (thisRoom.Clients.Contains(newClient))
                    {
                        // client is already a member of this room. Not allowed to re-join.
                        throw new DuplicateRoomMemberException("A conta de e-mail escolhida já faz parte desta sala de chat.");
                    }
                }

                if (thisRoom.MaxUsers > 0 &&
                    thisRoom.Clients.Count >= thisRoom.MaxUsers)
                {
                    throw new FullChatRoomException("A sala já está lotada. Você será colocado na fila de espera.");
                }
                
                thisRoom.Clients.Add(newClient);
                db.SaveChanges();

                CTClient ctClnt = new CTClient(_sName, _sEmail);
                this.ClientList.Add(ctClnt);
                
                return ctClnt;
            }
        }

        internal CTClient RemoveClient(string _sEmail)
        {
            using (CloudTalkEntities db = new CloudTalkEntities())
            {
                ChatRoom thisRoom = db.ChatRoom
                    .Include(r => r.Clients)
                    .FirstOrDefault(cr => cr.ID == this.ID);

                Client clientToRemove = thisRoom.Clients.FirstOrDefault(cl => cl.Email == _sEmail);

                if (clientToRemove == null)
                {
                    throw new InvalidOperationException("There is no client with the specified email in the chat room.");
                }

                thisRoom.Clients.Remove(clientToRemove);

                CTClient removedClient = this.ClientList.FirstOrDefault(clt => clt.Email == _sEmail);
                this.ClientList.Remove(removedClient);

                // Do not remove the client from the database. Just remove association with the chat room.
                //db.DeleteObject(clientToRemove);

                db.SaveChanges();

                return removedClient;
            }
        }

        internal void ClearClients()
        {
            using (CloudTalkEntities db = new CloudTalkEntities())
            {
                var chatRoom = db.ChatRoom
                    .Include(r => r.Clients)
                    .FirstOrDefault(cr => cr.ID == this.ID);

                chatRoom.Clients.ToList().ForEach(cr =>
                {
                    chatRoom.Clients.Remove(cr);
                });

                db.SaveChanges();

                this.ClientList.Clear();
            }
        }
    }

    public enum RoleTypes
    {
        Member,
        Moderator,
        Assistant
    }
}
